﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BasketballAI.Infrastructure.Entity;
using System.Drawing;

namespace BasketballAI.Infrastructure.GameItems
{
    public class Ball:IItem
    {
        #region Members
        public delegate void delegateBallMove(Point newPosition);
        public delegateBallMove BallEvent;
        private Point destinationOnCourtPix;
        private Point positionOnCourtPix;


        #endregion

        #region Constructors

        public Ball(Point position, BasketballAI.Infrastructure.Global.AstarPosition aStarPosition)
        {
            BallEvent = new delegateBallMove(BallMoveEvent);
            this.PositionOnCourtPix = position;
            this.AStarPosition = aStarPosition;           
        }

        #endregion

        #region Properties
        public Point DestinationOnCourtPix
        {
            get { return destinationOnCourtPix; }
            set { destinationOnCourtPix = value; }
        }
        public Point PositionOnCourtPix
        {
            get { return positionOnCourtPix; }
            set
            {
                positionOnCourtPix = value;
                if(this.BallEvent!=null)
                    this.BallEvent(positionOnCourtPix);
            }
        }

        #endregion

        #region Methods
        public void Move(Global.BallStrength strength)
        {
            double alpha, radians, dx, dy,epsilon=0.001;
            bool isMovingForward, isMovingUp;
            int newx, newy;
            int quarter=1;
            if (this.destinationOnCourtPix != null && this.PositionOnCourtPix != this.destinationOnCourtPix)
            {
                if ((this.destinationOnCourtPix.X - this.PositionOnCourtPix.X) != 0)
                    radians = Math.Atan(Math.Abs((double)(this.destinationOnCourtPix.Y - this.PositionOnCourtPix.Y) / (double)(this.destinationOnCourtPix.X - this.PositionOnCourtPix.X)));
                else
                    radians = Math.Atan(Math.Abs((double)(this.destinationOnCourtPix.Y - this.PositionOnCourtPix.Y) / epsilon));
                alpha = radians * (180 / Math.PI);
                if (this.PositionOnCourtPix.X <= this.destinationOnCourtPix.X)
                    isMovingForward = true;
                else
                    isMovingForward = false;

                if (this.PositionOnCourtPix.Y < this.destinationOnCourtPix.Y)                                 
                    isMovingUp = true;                
                else                                 
                    isMovingUp = false;
                if (isMovingForward && isMovingUp)
                        quarter = 1;
                else if (!isMovingForward && isMovingUp)
                {
                    radians = Math.PI - radians;
                    quarter = 2;
                }
                else if (!isMovingForward && !isMovingUp)
                {
                    radians += Math.PI;
                    quarter = 3;
                }
                else if (isMovingForward && !isMovingUp)
                {
                    radians = 2 * Math.PI - radians;
                        quarter = 4;
                }
               //Calculation of power.              
                switch (strength)
                {
                    case Global.BallStrength.Soft:
                        {
                            dx = 7 * Math.Cos(radians);
                            dy = 7 * Math.Sin(radians);
                            break;
                        }
                    case Global.BallStrength.Medium:
                        {
                            dx = 10 * Math.Cos(radians);
                            dy = 10 * Math.Sin(radians);
                            break;
                        }
                    case Global.BallStrength.Hard:
                        {
                            dx = 15 * Math.Cos(radians);
                            dy = 15 * Math.Sin(radians);
                            break;
                        }
                    default:
                        {
                            dx = 10 * Math.Cos(radians);
                            dy = 10 * Math.Sin(radians);
                            break;
                        }
                }
                switch (quarter)
                {
                    case 1:// x>0 , y>0
                        {        
                            if ((this.PositionOnCourtPix.X + Convert.ToInt32(dx)) <= this.destinationOnCourtPix.X)
                                newx = this.PositionOnCourtPix.X + Convert.ToInt32(dx);
                            else
                                newx = this.destinationOnCourtPix.X;

                            if ((this.PositionOnCourtPix.Y + Convert.ToInt32(dy)) <= this.destinationOnCourtPix.Y)
                                newy = this.PositionOnCourtPix.Y + Convert.ToInt32(dy);
                            else
                                newy = this.destinationOnCourtPix.Y;
                            break;
                        }
                    case 2://x<0 , y>0
                        {
                            if ((this.PositionOnCourtPix.X + Convert.ToInt32(dx)) >= this.destinationOnCourtPix.X)
                                newx = this.PositionOnCourtPix.X + Convert.ToInt32(dx);
                            else
                                newx = this.destinationOnCourtPix.X;

                            if ((this.PositionOnCourtPix.Y + Convert.ToInt32(dy)) <= this.destinationOnCourtPix.Y)
                                newy = this.PositionOnCourtPix.Y + Convert.ToInt32(dy);
                            else
                                newy = this.destinationOnCourtPix.Y;
                            break;
                        }
                    case 3://x<0 , y<0
                        {
                            if ((this.PositionOnCourtPix.X + Convert.ToInt32(dx)) >= this.destinationOnCourtPix.X)
                                newx = this.PositionOnCourtPix.X + Convert.ToInt32(dx);
                            else
                                newx = this.destinationOnCourtPix.X;

                            if ((this.PositionOnCourtPix.Y + Convert.ToInt32(dy)) >= this.destinationOnCourtPix.Y)
                                newy = this.PositionOnCourtPix.Y + Convert.ToInt32(dy);
                            else
                                newy = this.destinationOnCourtPix.Y;

                            break;
                        }
                    case 4://x>0, y<0
                        {
                            if ((this.PositionOnCourtPix.X + Convert.ToInt32(dx)) <= this.destinationOnCourtPix.X)
                                newx = this.PositionOnCourtPix.X + Convert.ToInt32(dx);
                            else
                                newx = this.destinationOnCourtPix.X;

                            if ((this.PositionOnCourtPix.Y + Convert.ToInt32(dy)) >= this.destinationOnCourtPix.Y)
                                newy = this.PositionOnCourtPix.Y + Convert.ToInt32(dy);
                            else
                                newy = this.destinationOnCourtPix.Y;
                            break;
                        }
                    default: //x>0 , y>0
                        {
                            if ((this.PositionOnCourtPix.X + Convert.ToInt32(dx)) <= this.destinationOnCourtPix.X)
                                newx = this.PositionOnCourtPix.X + Convert.ToInt32(dx);
                            else
                                newx = this.destinationOnCourtPix.X;

                            if ((this.PositionOnCourtPix.Y + Convert.ToInt32(dy)) <= this.destinationOnCourtPix.Y)
                                newy = this.PositionOnCourtPix.Y + Convert.ToInt32(dy);
                            else
                                newy = this.destinationOnCourtPix.Y;
                             break;
                        }

                }
                                
                this.PositionOnCourtPix = new Point(newx, newy);                                
                
            }
        }

        #endregion

        #region Events
        private void BallMoveEvent(Point p)
        {
            Point rp = new Point(0, 0);
            if (p != null)
            {
                rp.Y = Convert.ToInt32(Math.Floor((double)((p.X + 10 - 40) / 20)));
                rp.X = Convert.ToInt32(Math.Floor((double)((p.Y + 10 - 40) / 20)));                
            }
            this.PositionOnCourt = rp;
            
        }

        #endregion
    }
}
